package org.light.verb;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.light.core.Verb;
import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.Dropdown;
import org.light.domain.Field;
import org.light.domain.JavascriptBlock;
import org.light.domain.JavascriptMethod;
import org.light.domain.Method;
import org.light.domain.Signature;
import org.light.domain.Statement;
import org.light.domain.StatementList;
import org.light.domain.Type;
import org.light.easyui.EasyUIPositions;
import org.light.exception.ValidateException;
import org.light.generator.NamedStatementGenerator;
import org.light.utils.FieldUtil;
import org.light.utils.StringUtil;
import org.light.utils.WriteableUtil;

public class FilterPPT extends Verb implements EasyUIPositions {
	protected SearchByFields search = new SearchByFields();
	
	@Override
	public Method generateDaoImplMethod() throws Exception{
		return null;
	}

	@Override
	public Method generateDaoMethodDefinition()  throws Exception{
		return null;
	}

	@Override
	public Method generateServiceMethodDefinition()  throws Exception{
		return null;
	}

	@Override
	public Method generateServiceImplMethod()  throws Exception{
		return null;
	}
	
	public FilterPPT(){
		super();
		this.setLabel("PPT过滤");
	}
	
	public FilterPPT(Domain domain) throws ValidateException{
		super();
		this.domain = domain;
		this.denied = domain.isVerbDenied("FilterPPT");
		this.search = new SearchByFields(domain);
		this.setVerbName("FilterPPT"+StringUtil.capFirst(this.domain.getPlural()));
		this.setLabel("PPT过滤");
		if  (domain.getLanguage().equalsIgnoreCase("english"))  this.setLabel("FilterPPT");
	}

	public FilterPPT(Domain domain, Set<Field> deniedFields) throws ValidateException{
		super();
		this.domain = domain;
		this.dbType = domain.getDbType();
		this.deniedFields = deniedFields;
		this.denied = domain.isVerbDenied("FilterPPT");
		this.search = new SearchByFields(domain);
		this.setVerbName("FilterPPT"+StringUtil.capFirst(this.domain.getPlural()));
		this.setLabel("PPT过滤");
		if  (domain.getLanguage().equalsIgnoreCase("english"))  this.setLabel("FilterPPT");
	}

	@Override
	public Method generateControllerMethod()  throws Exception{
		if (this.denied)
			return null;
		else {
			this.search.setDomain(this.domain);
			
			Method method = new Method();
			method.setStandardName("processRequest");
			method.setReturnType(new Type("void"));
			method.setThrowException(true);
			List<String> list = new ArrayList<String>();
			list.add("ServletException");
			list.add("IOException");
			method.setIsprotected(true);
			method.setOtherExceptions(list);
			method.addSignature(new Signature(1,"request",new Type("HttpServletRequest","javax.servlet.http")));
			method.addSignature(new Signature(2,"response",new Type("HttpServletResponse","javax.servlet.http")));
			method.addAdditionalImport("java.io.IOException");
			method.addAdditionalImport("javax.servlet.ServletException");
			method.addAdditionalImport("javax.servlet.http.HttpServlet");
			method.addAdditionalImport("javax.servlet.http.HttpServletRequest");
			method.addAdditionalImport("javax.servlet.http.HttpServletResponse");
			method.addAdditionalImport("java.util.List");
			method.addAdditionalImport("java.util.ArrayList");
			method.addAdditionalImport("java.io.OutputStream");
			method.addAdditionalImport("java.util.Arrays");
			method.addAdditionalImport(this.domain.getPackageToken()+".utils.POIPPTUtil");
			method.addAdditionalImport(this.domain.getPackageToken()+".utils.BooleanUtil");
			method.addAdditionalImport(this.domain.getPackageToken()+".utils.StringUtil");
			method.addAdditionalImport(this.domain.getPackageToken()+ "."+this.domain.getDomainSuffix()+"."+this.domain.getCapFirstDomainNameWithSuffix());
			method.addAdditionalImport(this.domain.getPackageToken()+"."+this.domain.getServiceSuffix()+"."+this.domain.getStandardName()+"Service");
			method.addAdditionalImport(this.domain.getPackageToken()+"."+this.domain.getServiceimplSuffix()+"."+this.domain.getStandardName()+"ServiceImpl");

			for (Field f:this.domain.getFields()) {
				if (!this.deniedFields.contains(f)) {
					if (f instanceof Dropdown) {
						Dropdown dp = (Dropdown)f;
						method.addAdditionalImport(this.domain.getPackageToken()+"."+this.domain.getDomainSuffix()+"."+dp.getTarget().getCapFirstDomainNameWithSuffix());
						method.addAdditionalImport(this.domain.getPackageToken()+"."+this.domain.getServiceSuffix()+"."+dp.getTargetName()+"Service");
						method.addAdditionalImport(this.domain.getPackageToken()+"."+this.domain.getServiceimplSuffix()+"."+dp.getTargetName()+"ServiceImpl");
					}
				}
			}

			if (this.domain.containsDateTime()) {
				method.addAdditionalImport(this.domain.getPackageToken()+".utils.DateUtil");
			}

			List<Writeable> sList = new ArrayList<Writeable>();
			long serial = 1000L;
			for (Field f: this.domain.getSearchFields()){
				if (!this.deniedFields.contains(f)) {
					sList.add(NamedStatementGenerator.getFacadeGetParameterByFieldClassTypeSetNull(serial,2,f.getLowerFirstFieldName(),f.getFieldType()));
					serial +=  1000L;
				}
			}
			sList.add(new Statement(serial+1000L,2,this.domain.getCapFirstDomainNameWithSuffix()+" "+this.domain.getLowerFirstDomainName()+"0 = new "+this.domain.getCapFirstDomainNameWithSuffix()+"();"));
			
			serial += 2000L;
			for (Field f: this.domain.getSearchFields()){
				if (!this.deniedFields.contains(f)) {
					if ("date".equalsIgnoreCase(f.getFieldType())){
						sList.add(new Statement(serial,2, domain.getLowerFirstDomainName()+"0."+f.getSetterCallName()+"(DateUtil.strDateToUtilDate("+f.getLowerFirstFieldName()+"));"));
						serial +=  1000L;
					} else if ("datetime".equalsIgnoreCase(f.getFieldType())){
						sList.add(new Statement(serial,2, domain.getLowerFirstDomainName()+"0."+f.getSetterCallName()+"(DateUtil.strDateTimeToUtilDateTime("+f.getLowerFirstFieldName()+"));"));
						serial +=  1000L;
					} else {
						sList.add(NamedStatementGenerator.getSetFieldValueByDomainAliasWithVarNameByFieldClassType(serial,2,this.domain,f.getLowerFirstFieldName(),this.domain.getLowerFirstDomainName()+"0"));
						serial +=  1000L;
					}
				}
			}
			
			sList.add(new Statement(serial+1000L,2,"try(OutputStream out = response.getOutputStream()){"));
			sList.add(new Statement(serial+2000L,3,"try{"));
			sList.add(new Statement(serial+3000L,4,"response.addHeader(\"Content-Disposition\", \"attachment;filename="+this.domain.getCapFirstPlural()+".pptx\");"));
			sList.add(new Statement(serial+4000,4,this.domain.getStandardName()+"Service service  = new " + this.domain.getStandardName()+"ServiceImpl();"));
			serial += 5000L;
			Set<String> dpDomainNames = new TreeSet<>();
			for (Field f:this.domain.getFields()) {
				if (!this.deniedFields.contains(f)) {
					if (f instanceof Dropdown) {
						Dropdown dp = (Dropdown)f;
						dpDomainNames.add(dp.getTargetName());
					}
				}
			}
			for (String dName :dpDomainNames){
				sList.add(new Statement(serial,4,StringUtil.capFirst(dName)+"Service "+StringUtil.lowerFirst(dName)+"Service  = new " + StringUtil.capFirst(dName)+"ServiceImpl();"));
				serial += 1000L;
			}
			sList.add(new Statement(serial+3000L,4,"List<"+this.domain.getCapFirstDomainNameWithSuffix()+"> list = service.search"+this.domain.getCapFirstPlural()+"ByFields("+this.domain.getLowerFirstDomainName()+"0);"));
			sList.add(new Statement(serial+4000L,4,"List<List<Object>> contents = new ArrayList<>();"));
			if  (domain.getLanguage().equalsIgnoreCase("english"))  {
				sList.add(new Statement(serial + 5000L,4,"String sheetName = \""+this.domain.getText()+" Information\";"));
			}else {
				sList.add(new Statement(serial + 5000L,4,"String sheetName = \""+this.domain.getText()+"信息表\";"));			
			}
			sList.add(new Statement(serial+6000L,4,"String [] headers = "+this.domain.generateFieldLabelsArrayStr(FieldUtil.filterDeniedFields(this.domain.getFields(), this.deniedFields))+";"));
			sList.add(new Statement(serial+6500L,4,"Boolean [] isImages = "+this.domain.generateIsImageFieldsArrayStr(FieldUtil.filterDeniedFields(this.domain.getFields(), this.deniedFields))+";"));
			sList.add(new Statement(serial+7000L,4,""));
			sList.add(new Statement(serial+8000L,4,"for ("+this.domain.getCapFirstDomainNameWithSuffix()+" "+this.domain.getLowerFirstDomainName()+":list) {"));
			serial += 9000L;
			for (Field f:FieldUtil.filterDeniedFields(this.domain.getFields(), this.deniedFields)) {
				if (!this.deniedFields.contains(f)) {
					if (f instanceof Dropdown) {
						Dropdown dp = (Dropdown)f;
						sList.add(new Statement(serial,5,f.getFieldType()+ " "+f.getLowerFirstFieldName()+"0 = "+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"();"));
						sList.add(new Statement(serial+500L,5,dp.getTarget().getType()+" " +dp.getAliasName()+"Type0;"));
						sList.add(new Statement(serial+1000L,5,dp.getTarget().getDomainName().getFieldType()+" " +dp.getAliasName()+"Name0 = \"\";"));
						sList.add(new Statement(serial+2000L,5,"if ("+f.getLowerFirstFieldName()+"0 != null) {"));
						sList.add(new Statement(serial+2100L,6,dp.getAliasName()+"Type0 = "+StringUtil.lowerFirst(dp.getTargetName())+"Service.find"+dp.getTarget().getCapFirstDomainName()+"By"+dp.getTarget().getDomainId().getCapFirstFieldName()+"("+f.getLowerFirstFieldName()+"0);"));
						sList.add(new Statement(serial+2200L,6,"if ("+dp.getAliasName()+"Type0 !=null) "+dp.getAliasName()+"Name0 = "+dp.getAliasName()+"Type0.get"+dp.getTarget().getDomainName().getCapFirstFieldName()+"();"));
						sList.add(new Statement(serial+2300L,5,"}"));
						serial+=3000L;
					}
				}
			}
			String sc = "Object [] row = {";
			for (Field f:FieldUtil.filterDeniedFields(this.domain.getFields(), this.deniedFields)) {
				if (!this.deniedFields.contains(f)) {
					if (f instanceof Dropdown) {
						Dropdown dp = (Dropdown)f;
						sc += dp.getAliasName() + "Name0,";
					}else {
						if (f.getFieldType().equalsIgnoreCase("String")||f.getFieldType().equalsIgnoreCase("image")) {
							sc += this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"(),";
						} else if (f.getFieldType().equalsIgnoreCase("date")) {
							sc += "DateUtil.utilDateToString("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"()),";
						} else if (f.getFieldType().equalsIgnoreCase("datetime")) {
							sc += "DateUtil.utilDateTimeToString(" + this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"()),";
						} else {
							sc += "StringUtil.toNullString("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"()),";
						}
					}
				}
			}
			if (FieldUtil.filterDeniedFields(this.domain.getFields(), this.deniedFields)!=null && FieldUtil.filterDeniedFields(this.domain.getFields(), this.deniedFields).size()>0) {
				sc = sc.substring(0,sc.length()-1);
			}
			sc += "};";
			sList.add(new Statement(serial,5,sc));
			sList.add(new Statement(serial+1000L,5,"contents.add(Arrays.asList(row));"));
			sList.add(new Statement(serial+2000L,4,"}"));
			sList.add(new Statement(serial+3000L,4,""));
			sList.add(new Statement(serial+4000L,4,"POIPPTUtil.exportPPTWithImage(out, sheetName, Arrays.asList(headers), contents, Arrays.asList(isImages));"));
			sList.add(new Statement(serial+5000L,3,"} catch (Exception e) {"));
			sList.add(new Statement(serial+6000L,4,"ServletException se = new ServletException();"));
			sList.add(new Statement(serial+7000L,4,"se.setStackTrace(e.getStackTrace());"));
			sList.add(new Statement(serial+8000L,4,"throw se;"));
			sList.add(new Statement(serial+9000L,3,"}"));	
			sList.add(new Statement(serial+10000L,2,"}"));	
			method.setMethodStatementList(WriteableUtil.merge(sList));
			
			return method;
		}
	}

	@Override
	public JavascriptBlock generateEasyUIJSButtonBlock() throws Exception {
		return null;
	}

	@Override
	public JavascriptMethod generateEasyUIJSActionMethod() throws Exception {
		if (this.denied)
			return null;
		else {
			Domain domain = this.domain;
			JavascriptMethod method = new JavascriptMethod();
			method.setSerial(200);
			method.setStandardName("filterPPT"+domain.getPlural());
					
			StatementList sl = new StatementList();
			sl.add(new Statement(1000,1, "params = {"));
			long serial = 2000;
			for (Field f : domain.getSearchFields()) {
				if (!deniedFields.contains(f)) {
					if (f instanceof Dropdown) {
						sl.add(new Statement(serial, 2, f.getLowerFirstFieldName() + ":$(\"#ffsearch\").find(\"#"
								+ f.getLowerFirstFieldName() + "\").combobox(\"getValue\"),"));
					} else if (!f.getFieldType().equalsIgnoreCase("boolean")) {
						if ("datetime".equalsIgnoreCase(f.getFieldType())) {
							sl.add(new Statement(serial, 2, f.getLowerFirstFieldName() + ":$(\"#ffsearch\").find(\"#"
									+ f.getLowerFirstFieldName() + "\").datetimebox(\"getValue\"),"));
						} else if ("date".equalsIgnoreCase(f.getFieldType())) {
							sl.add(new Statement(serial, 2, f.getLowerFirstFieldName() + ":$(\"#ffsearch\").find(\"#"
									+ f.getLowerFirstFieldName() + "\").datebox(\"getValue\"),"));
						} else {
							sl.add(new Statement(serial, 2, f.getLowerFirstFieldName() + ":$(\"#ffsearch\").find(\"#"
								+ f.getLowerFirstFieldName() + "\").val(),"));
						}
					} else if (f.getFieldType().equalsIgnoreCase("boolean")) {
						sl.add(new Statement(serial, 2, f.getLowerFirstFieldName()
								+ ":parseBoolean($(\"#ffsearch\").find(\"#" + f.getLowerFirstFieldName() + "\").val()),"));
					}
					serial += 1000;
				}
			}
			sl.add(new Statement(serial,1, "};"));
			sl.add(new Statement(serial+1000,1, "var params0 = $.param(params);"));
			sl.add(new Statement(serial+2000,1, "document.location.href = \"../"+this.domain.getLowerFirstDomainName()+domain.getControllerNamingSuffix()+"/filterPPT"+this.domain.getCapFirstPlural()+"?\" + params0;"));
		    
			method.setMethodStatementList(sl);
			return method;	
		}
	}

	public SearchByFields getSearch() {
		return search;
	}

	public void setSearch(SearchByFields search) {
		this.search = search;
	}

	@Override
	public Method generateDummyDaoImplMethod() throws Exception {
		return null;
	}

	@Override
	public Method generateDummyServiceImplMethod() throws Exception {
		return null;
	}

	@Override
	public Method generateDummyDaoMethodDefinition() throws Exception {
		return null;
	}
}
